#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
#include <string.h>
#include <unistd.h>
#include <fstream>
#include <thread>
#include <fcntl.h>
#include <signal.h>

// #include "Thread.h"
#include "SimulationServer.h"
#include "ConfigImport.h"
#include <armadillo>

#define DEBUG

#if 0
ServerFunProvider::ServerFunProvider()
{ 
}
ServerFunProvider::~ServerFunProvider()
{
}

int ServerFunProvider::RunExecuteFunction(void* args)
{
    struct SimulationServerParameterStr*serverParaPtr = (struct SimulationServerParameterStr*)args;
    // printf("this is ServerFun\n");
    char *message = serverParaPtr->messageFromClient;
    arma::fcube data_predict;
    ConfigImport* sys_config = serverParaPtr->configPara;

    data_predict.load(sys_config->configMap["testFileName"], arma::raw_binary);
    data_predict.reshape(sys_config->test_dim[0],sys_config->test_dim[1],sys_config->test_dim[2]);

    bool endFlag = 0;
    int index = 0;
    while(!endFlag){

        // 获取客户端发送的消息
        int n = read(serverParaPtr->client_socket_fd, message, sizeof(message));
        if(n == -1){
            // printf("read error: %s(errno: %d)\n",strerror(errno),errno);
            #ifdef WARN
            printf(" == warning: Call blocking operation in non blocking mode ==\n");
            #endif // WARN
            // break;
        }

        arma::fmat single_frame = arma::conv_to<arma::fmat>::from(data_predict.slice(index));

        size_t writeLen = write(serverParaPtr->client_socket_fd, 
                reinterpret_cast<const void *>(single_frame.memptr()),
                single_frame.n_elem * sizeof(float));
        // single_frame.print("frame:");
        printf("writeLen = %ld\n",writeLen);
        usleep(10000);
        
        if(n == 0){
            printf("客户端已退出...\n");
            break;
        }
        
        // 服务函数
        #ifdef CALLBACK
        if(n > 0){
            // char* buff = (char*) messageData;
            std::string msg = "";
            // buff[messageLen] = 0;
            msg.append(buff);
            int w_len = write(clientParaPtr->client_socket_fd, msg.c_str(), msg.size());
            std::cout << "client# " << msg << std::endl;

            if(w_len < 0){
                printf(" == 发送出错，断开连接！！== \n");
                break;
            }
        }
        #endif // CALLBACK



        ++index;
        if(index >= data_predict.n_slices){
            printf("over\n");
            break;
        }
    }
    close(serverParaPtr->client_socket_fd);
    return 0;
}

SimulationServer::SimulationServer(int serverPort)
                    // :Thread(pExecuteFunctionProvider)
{
    // m_pExecuteFunctionProvider = pExecuteFunctionProvider;
    // 创建一个TCP服务端
    int res = server_socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    if(res == -1){
        printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);
        return ;
    }
    printf(" === server running. ===\n");

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_port = htons(serverPort);
    //设置端口可重用
    int contain;
    setsockopt(server_socket_fd,SOL_SOCKET, SO_REUSEADDR, &contain, sizeof(int));

    if( bind(server_socket_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1){
        printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);
    }
    // printf("----bind sucess----\n");

    if( listen(server_socket_fd, 10) == -1){
        printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);
    }
    printf("====== waiting for client's request ======\n");
}

SimulationServer::~SimulationServer()
{
    close(server_socket_fd);
    printf("======server shut down=====\n");
}

void SimulationServer::task()
{
    ConfigImport *configPara = ConfigImport::getInstance();

    while(1){
        struct sockaddr_in client_addr;
        socklen_t size=sizeof(client_addr);

        // 等待客户端连接请求
        // client_socket_fd = accept(server_socket_fd, (struct sockaddr*)&client_addr, &size);
        client_socket_fd = accept4(server_socket_fd, (struct sockaddr*)&client_addr, &size, SOCK_NONBLOCK);
        if(client_socket_fd == -1){
            printf("accept socket error: %s(errno: %d)",strerror(errno),errno);
            continue;
        }

        // 获取连接上服务端的客户端的ip和port
        const char *client_ip = inet_ntoa(client_addr.sin_addr);
        uint16_t client_port = ntohs(client_addr.sin_port);
        std::cout << "客户端:[" << client_ip << ":" << client_port << "]已连接...." << std::endl;

        
        // 创建一个子线程用于和客户端通信
        // 线程执行体指针，用于调用服务函数
        #if 0
        pthread_t tid;
        pthread_create(&tid, nullptr, tfun, (void*)&client_socket_fd);
        pthread_detach(tid);
        #else

        ExecuteFunctionProvider *serverFunProvider = new ServerFunProvider();
        // 基于线程的执行体,不分离子线程，第二个参数传1
        Execute* server_pThread = new Thread(serverFunProvider,1);
        std::cout << "addr:" << server_pThread << std::endl;
        // 线程开始运行
        // 上下文传递
        struct SimulationServerParameterStr serverPara = {0};
        serverPara.client_socket_fd = client_socket_fd;
        serverPara.configPara = configPara;

        server_pThread->Run((void*)&serverPara);
        // server_pThread->detach();
        server_pThread->WaitForDeath();
        #endif

    }
}

int main(int argc, char const *argv[])
{
    // ExecuteFunctionProvider *serverFunProvider = new ServerFunProvider();
    SimulationServer* pServer = new SimulationServer();
    pServer->task();
    return 0;
}
#else
TCPServer::TCPServer(int serverPort)
{
    workingFlag = true;
    // 创建一个TCP服务端
    int res = server_socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    if(res == -1){
        printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);
    }
    printf("----init socket----\n");

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_port = htons(serverPort);
    //设置端口可重用
    int contain;
    setsockopt(server_socket_fd,SOL_SOCKET, SO_REUSEADDR, &contain, sizeof(int));

    if( bind(server_socket_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1){
        printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);
    }
    printf("----bind sucess----\n");

    if( listen(server_socket_fd, 10) == -1){
        printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);
    }
    printf("======waiting for client's request======\n");
}

TCPServer::~TCPServer()
{
    close(server_socket_fd);
    printf("======server shut down=====\n");
}

// void TCPServer::message_parsing(void* messageData, int messageLen){
//     char* buff = (char*) messageData;
//     std::string msg = "";
//     buff[messageLen]=0;
//     msg.append(buff);
//     write(client_socket_fd, msg.c_str(), msg.size());
//     std::cout << "client# " << msg << std::endl;
// }

bool TCPServer::message_parsing(ConfigImport* sys_config){
    #if 1
    arma::fcube data_predict;
    data_predict.load(sys_config->configMap["testFileName"], arma::raw_binary);
    data_predict.reshape(sys_config->test_dim[0],1,sys_config->test_dim[1]*sys_config->test_dim[2]);

    // printf("data_predict:%d*%d*%d\n", data_predict.n_rows, data_predict.n_cols, data_predict.n_slices);

    // 发送频率1kHz
    int times = data_predict.n_slices;
    for (int index = 0; index<times; ++index){
        arma::fmat single_frame = arma::conv_to<arma::fmat>::from(data_predict.slice(index));
        size_t writeLen = write(client_socket_fd, 
                reinterpret_cast<const void *>(single_frame.memptr()),
                single_frame.n_elem * sizeof(float));
        
        #ifdef DEBUG
        printf("send len:%ld\tslice:%d\n",writeLen,index);
        #endif

        // 等待1ms
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
        // while(1);
    }
    // single_frame.print("frame:");
    // printf("writeLen = %ld\n",writeLen);
    #else
    int fd;
    int nread; 
    int nwrite, i;
    char buffer[MAXLINE];
    std::ifstream file(sys_config->configMap["testFileName"], std::ios::binary);
    if (!file.is_open()) {
        std::cerr << "Failed to open file.\n";
        return true;
    }

    long long int read_sum = 0; 
    bool send_ready = false;
    while(!send_ready){

        // 读取文件内容
        file.read(buffer, sizeof(buffer));
        std::streamsize nread = file.gcount();
        read_sum += nread;
        if (!file) {
            if (file.eof()) {
                std::cout << "End of file reached.\n";
                file.close();
                printf("read_sum = %lld\n",read_sum);
                send_ready = true;
            }
            else {
                std::cerr << "Failed to read file.\n";
                return true;
            }
        }


        for (i=0; i<nread; i += nwrite) {
            nwrite = write(client_socket_fd, buffer + i, nread - i);
            if (nwrite < 0) {
                std::cerr << "socket write error!" << std::endl;
                printf("nwrite = %d\n",nwrite);
                return true;
            }
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(1));

    }
    #endif

    return true;

}

void TCPServer::task()
{
    std::vector<std::thread> client_threads;
    while(workingFlag){
        struct sockaddr_in client_addr;
        socklen_t size=sizeof(client_addr);
        int  n;
        bool client_task_over = false;

        // 等待客户端连接请求,非阻塞
        client_socket_fd = accept4(server_socket_fd, (struct sockaddr*)&client_addr, &size, SOCK_NONBLOCK);
        // client_socket_fd = accept(server_socket_fd, (struct sockaddr*)&client_addr, &size);
        if(client_socket_fd == -1){
            printf("accept socket error: %s(errno: %d)",strerror(errno),errno);
            continue;
        }

        // 获取连接上服务端的客户端的ip和port
        const char *client_ip = inet_ntoa(client_addr.sin_addr);
        uint16_t client_port = ntohs(client_addr.sin_port);
        std::cout << "客户端:[" << client_ip << ":" << client_port << "]已连接...." << std::endl;
        
        ConfigImport *configPara = ConfigImport::getInstance();
        // // 非阻塞连接
        // int flags = fcntl(client_socket_fd, F_GETFL, 0);
        // flags |= O_NONBLOCK;
        // fcntl(client_socket_fd, F_SETFL, flags);

        while(!client_task_over && workingFlag){
        // while(true){        //循环发送一个文件
            // 获取客户端发送的消息
            n = read(client_socket_fd, buff, MAXLINE);
            if(n == 0){
                std::cout<<"客户端已退出..."<<std::endl;
                break;
            }
            client_task_over = message_parsing(configPara);
        }
        close(client_socket_fd);
    }
}

void TCPServer::processShutdown(){
    workingFlag = false;
}

TCPServer *server;

// 信号处理函数
void handleSigTerm(int signal) {
    std::cout << "Received SIGTERM, performing cleanup..." << std::endl;
    // 子进程的清理操作
    server->processShutdown();
    exit(0);  // 正常退出
}

int main(){
    // 设置 SIGTERM 信号处理器
    signal(SIGTERM, handleSigTerm);
    server = new TCPServer();
    server->task();
    return 0;
}

#endif